package com.sunwayworld.basemodule.rm.train.exampaper.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


import com.sunwayworld.basemodule.rm.train.exampaper.bean.LimsCoreExamPaperAnswerBean;
import com.sunwayworld.basemodule.rm.train.exampaper.bean.LimsCoreExamPaperAnswerCardDTO;
import com.sunwayworld.basemodule.rm.train.exampaper.bean.LimsCoreExamPaperBean;
import com.sunwayworld.basemodule.rm.train.exampaper.dao.LimsCoreExamPaperAnswerDao;
import com.sunwayworld.basemodule.rm.train.exampaper.service.LimsCoreExamPaperAnswerService;
import com.sunwayworld.basemodule.rm.train.exampaper.service.LimsCoreExamPaperService;
import com.sunwayworld.basemodule.rm.train.question.bean.LimsCoreQuestionOptBean;
import com.sunwayworld.basemodule.rm.train.question.service.LimsCoreQuestionOptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.audit.aunnotation.Audit;
import com.sunwayworld.framework.audit.constant.AuditConstant;
import com.sunwayworld.framework.constant.Constant;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.data.page.Pagination;
import com.sunwayworld.framework.database.sql.Order;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.utils.ObjectUtils;
import com.sunwayworld.framework.utils.ReflectionUtils;
import com.sunwayworld.framework.utils.StringUtils;

@Repository
@GikamBean
public class LimsCoreExamPaperAnswerServiceImpl implements LimsCoreExamPaperAnswerService {

    @Autowired
    private LimsCoreExamPaperAnswerDao coreExamPaperAnswerDao;
    
    @Autowired
    @Lazy
    private LimsCoreQuestionOptService coreQuestionOptService;
    
    @Autowired
    @Lazy
    private LimsCoreExamPaperService coreExamPaperService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsCoreExamPaperAnswerDao getDao() {
        return coreExamPaperAnswerDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    @Audit(AuditConstant.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsCoreExamPaperAnswerBean coreExamPaperAnswer = jsonWrapper.parseUnique(LimsCoreExamPaperAnswerBean.class);
        coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(coreExamPaperAnswer);
        return coreExamPaperAnswer.getId();
    }

    @Override
    public Pagination<LimsCoreExamPaperAnswerCardDTO> selectExamPaperAnswerCardByExamPaperId(Long examPaperId) {
        List<LimsCoreExamPaperAnswerBean> examPaperAnswerList = coreExamPaperAnswerDao.selectListByOneColumnValue(examPaperId, "EXAMPAPERID", Order.asc("ORDERNO"));
        
        int totalQty = examPaperAnswerList.size();
        int lineNum = totalQty % 4 == 0 ? totalQty / 4 : totalQty / 4 + 1;
        
        List<LimsCoreExamPaperAnswerCardDTO> answerCardList = new ArrayList<>();
        for (int i = 0; i < lineNum; i++) {
            List<LimsCoreExamPaperAnswerBean> subExamPaperAnswerList = (i * 4 + 4) > totalQty ? examPaperAnswerList.subList(i * 4, totalQty) : examPaperAnswerList.subList(i * 4, i * 4 + 4);
            
            LimsCoreExamPaperAnswerCardDTO answerCard = new LimsCoreExamPaperAnswerCardDTO();
            subExamPaperAnswerList.get(0).getExamQuestionId();
            for (int j = 0; j < subExamPaperAnswerList.size(); j++) {
                String columnValueProperty = "columnValue" + (j + 1);
                String answeredProperty = "answered" + (j + 1);
                
                LimsCoreExamPaperAnswerBean examPaperAnswer = subExamPaperAnswerList.get(j);
                
                ReflectionUtils.invokeWriteMethod(answerCard, columnValueProperty, examPaperAnswer.getOrderNo());
                if (StringUtils.isEmpty(examPaperAnswer.getAnswer())) {
                    ReflectionUtils.invokeWriteMethod(answerCard, answeredProperty, Constant.NO);
                } else {
                    ReflectionUtils.invokeWriteMethod(answerCard, answeredProperty, Constant.YES);
                }
            }
            answerCardList.add(answerCard);
        }
        return new Pagination<>(answerCardList);
    }

    @Override
    public LimsCoreExamPaperAnswerBean selectExamPaperAnswerCardByExamPaperId(Long examPaperId, Integer orderNo) {
        return selectFirstByFilter(SearchFilter.instance().match("EXAMPAPERID", examPaperId).filter(MatchPattern.EQ).match("ORDERNO", orderNo).filter(MatchPattern.EQ));
    }

    @Override
    public LimsCoreExamPaperAnswerBean selectExamPaperAnswerById(Long id) {
        return selectDetail(id);
    }

    @Override
    public Pagination<LimsCoreQuestionOptBean> selectQuestionOptPaginationByAnswerId(Long answerId, RestJsonWrapperBean wrapper) {
        LimsCoreExamPaperAnswerBean examPaperAnswer = selectDetail(answerId);
        
        List<LimsCoreQuestionOptBean> questionOptList = coreQuestionOptService.selectListByFilter(SearchFilter.instance().match("QUESTIONID", examPaperAnswer.getQuestionId()).filter(MatchPattern.EQ), wrapper);
        
        return new Pagination<>(questionOptList);
    }
    
    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.UPDATE)
    @Audit(AuditConstant.SAVE)
    public void updateIfChanged(List<LimsCoreExamPaperAnswerBean> itemList) {
        LimsCoreExamPaperAnswerService.super.updateIfChanged(itemList);
        
        List<Long> scoreChangedIdList = itemList.stream().filter(f -> !ObjectUtils.isEmpty(f.getScore())).map(LimsCoreExamPaperAnswerBean::getId).collect(Collectors.toList());
        if (scoreChangedIdList.isEmpty()) {
            return;
        }
        
        List<LimsCoreExamPaperAnswerBean> scoreChangedList = getDao().selectListByIds(scoreChangedIdList);
        
        List<Long> scoreChangedExamPaperIdList = scoreChangedList.stream().map(e -> e.getExamPaperId()).distinct().collect(Collectors.toList());
        
        List<LimsCoreExamPaperAnswerBean> examPaperAnswerList = getDao().selectListByOneColumnValues(scoreChangedExamPaperIdList, "EXAMPAPERID");
        
        List<LimsCoreExamPaperBean> examPaperList4Update = new ArrayList<>();
        
        scoreChangedExamPaperIdList.forEach(e -> {
            long totalScore = examPaperAnswerList.stream().filter(f -> f.getExamPaperId().equals(e)).mapToLong(LimsCoreExamPaperAnswerBean::getScore).sum();
            
            LimsCoreExamPaperBean examPaper4Update = new LimsCoreExamPaperBean();
            examPaper4Update.setId(e);
            examPaper4Update.setScore(totalScore);
            
            examPaperList4Update.add(examPaper4Update);
        });
        
        coreExamPaperService.getDao().update(examPaperList4Update, "SCORE");
    }
}